
import sdl2
from sketchz import *
from random import randint, choice
from itertools import product

window = Window((1000, 800))

window.img.clear_value = (0.6, 0.7, 0.8, 1)


ti = range(3)
v = list(product(ti, ti, ti))

id = 0
all_dict = {}
for p in v:
    all_dict[p] = id
    id += 1

v_dict = all_dict.copy()
print(len(all_dict))

for p in v:
    (i, j, k) = p
    for d in [1, -1]:
        for ne in [(i + d, j, k), (i, j + d, k), (i, j, k + d)]:
            if ne in all_dict:
                connect = frozenset([p, ne])
                if connect not in all_dict:
                    all_dict[connect] = id
                    id += 1

print(len(all_dict))



box = Obj100()
box.color = (1, 1, 1)
box.t.pos = U3(-1, -1,-1)
box1 = make_block(U3(1, 1, 1))
box1.as_unit() >> box
box.u(window)
box >> window


l = [[U3(0, 0, 0), 0] for _ in all_dict]

for p in v_dict:
    l[all_dict[p]][0] = U3(p[0], p[1], p[2])

l[all_dict[(1, 1, 1)]][1] = 1


box.update100(l)



camera = window.camera
camera.t.pos = U3(7, 7, 7)

walker = Viewer(camera)
walker >> window

def mirror_point(p):    # 不去重
    x, y, z = p
    l = [
    (x, y, z),
    (x, y, 2-z),
    (x, 2-y, z),
    (x, 2-y, 2-z),
    (2-x, y, z),
    (2-x, y, 2-z),
    (2-x, 2-y, z),
    (2-x, 2-y, 2-z),
    ]
    return l

def mirror_pair(p1, p2):    # 注意这里的connect要保持顺序，在下一步再转换成无序的
    l = zip(mirror_point(p1), mirror_point(p2))
    l = list(set(l))
    return l




class Ctrl(Control):
    def __init__(self):
        self.acc = 0
        bi = range(2)
        self.state = {p: 0 for p in product(bi, bi, bi)}
        self.state[(1, 1, 1)] = 1


    def reg_event(self, window):
        window.update_callback.append(self.update)

    def update(self, window, dt):
        self.acc += dt
        if self.acc >= 1:
            self.acc = 0
            print("tick")
            yes = [p for p in self.state if self.state[p] == 1]
            it = choice(yes)
            x, y ,z = it
            other, delete = None, None
            for i in range(10):
                other = choice([(1- x, y, z), (x, 1-y, z), (x, y, 1-z), ])
                delete = choice([True, False])
                if self.state[other] == 1 and delete == False:
                    continue
                else:
                    break
            self.state[other] = 1
            if delete:
                self.state[it] = 0
                for p in mirror_point(it):
                    l[all_dict[p]][1] = 0
            passer = Passer(0.7)
            connect = frozenset([it, other])
            for this, that in mirror_pair(it, other):
                connect = frozenset((this, that))
                l[all_dict[connect]][1] = 1
            def update(k):
                k = 1 - (1 - k) ** 3
                for this, that in mirror_pair(it, other):
                    connect = frozenset((this, that))
                    l[all_dict[connect]][0] = lerp(U3(*this), U3(*that), k)
                box.update100(l)

            passer.f = update

            def end():
                for this, that in mirror_pair(it, other):
                    connect = frozenset((this, that))
                    l[all_dict[connect]][1] = 0
                for p in mirror_point(other):
                    l[all_dict[p]][1] = 1
                box.update100(l)
            passer.endf = end

            passer.reg_event(window)

class Passer(Control):
    def __init__(self, t):
        self.t = t
        self.acc = 0
        self.f = None
        self.endf = None

    def reg_event(self, window):
        print("passer reg")
        window.update_callback.append(self.update)

    def unreg_event(self, window):
        window.update_callback.remove(self.update)

    def update(self, window, dt):
        print("xxx")
        self.acc += dt
        if self.acc >= self.t:
            window.update_callback.remove(self.update)
            if self.endf is not None:
                self.endf()
        if self.f is not None:
            self.f(self.acc / self.t)



Ctrl() >> window



window.mainloop()





